/*----------------------------------------------------------------------------------------
*
*  Copyright 2019, Gao Hai Hui, <fromzeropoint@126.com>.  All rights reserved.
*  https://gitee.com/helloworldghh/xos_http.git
*  Use of this source code is governed by a MIT license
*  that can be found in the License file.
*
----------------------------------------------------------------------------------------*/
#include "../import/head.h"
#include "../data_struct/head.h"
#include "../msg_notify/head.h"
#include "../config/head.h"
#include "../macro/head.h"
#include "../impl/head.h"
#include "../msg/head.h"
#include "fast_proc.h"
#include "http_proc.h"
#include "msg_fast.h"

namespace xos_http
{

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    msg_fast::msg_fast()
    {
    }

    msg_fast::~msg_fast()
    {
    }

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    // 
    // proc
    // 
    int msg_fast::proc( xos_box::i_msg *& pMsg )
    {
        int ret = 1;

        int nMsg = pMsg->get_msg();

        switch( nMsg )
        {
            case FAST_COMPOSE_RETURN:
            {
                fast_compose_return( pMsg );
            }
            break;
            case FAST_PARSE_REQUEST:
            {
                fast_parse_request( pMsg );
            }
            break;
            case FAST_PARSE_FAILED:
            {
                fast_parse_failed( pMsg );
            }
            break;
            case FAST_PROCESS:
            {
                fast_process( pMsg );
            }
            break;
            case FAST_SEND:
            {
                fast_send( pMsg );
            }
            break;
            case FAST_JOB:
            {
                fast_proc obj;
                obj.proc( pMsg );
            }
            break;

            // 
            // other
            // 
            default:
            {
                ret = 0;
            }
            break;
        }

        return ret;
    }

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    int msg_fast::fast_parse_request( xos_box::i_msg *& pMsg )
    {
        int ret = 0;

        xos_box::i_buf * pBuf = (xos_box::i_buf *)pMsg->get_buf( 0, 0 );
        connection * pConnect = (connection *)pMsg->get_void( 0, 0 );
        net::i_connect * pNetCon = pConnect->get_net_connect();
        http::i_request * pRequest = 0;

        // 如果是ssl网络事件，直接发送
        if( 0 == ret)
        {
            ret = pConnect->decode( pBuf );
            notify_tcp obj;
            if( 0 == ret )
            {
                if( pConnect->m_pSendNetEncodeDataList->size() > 0 )
                {
                    obj.post_send( pConnect, pConnect->m_pSendNetEncodeDataList, false, false );
                }
            }
            else
            {
                obj.post_reset( pMsg, pConnect );
            }
        }
        if( ( 0 == ret ) && ( 0 == pConnect->m_pRecvDataList->size() ) )
        {
            ret = 1;
        }
        if( 0 == ret )
        {
            if( !pConnect->m_pRecvTask )
            {
                xos_stl::init_pool_item( pConnect->m_pRecvTask );
                pConnect->m_pRecvTask->set_connect( pConnect->http_connect() );
            }
            if( !pConnect->m_bHttpFailed )
            {
                pRequest = pConnect->m_pRecvTask->http_request();
                pMsg->set_void( 0, pConnect->m_pRecvTask );
                pRequest->parse( pMsg );
            }
            else
            {
                ret = 1;
            }
        }

        if( 0 != ret )
        {
            pNetCon->release_ref();
        }

        xos_stl::release_interface( pBuf );

        return ret;
    }

    int msg_fast::fast_parse_failed( xos_box::i_msg *& pMsg )
    {
        int ret = 0;

        connection * pConnect = (connection *)pMsg->get_void( 0, 0 );
        net::i_connect * pNetCon = pConnect->get_net_connect();
        {
            notify_tcp obj;
            obj.post_reset( pMsg, pConnect );
            pNetCon->release_ref();
        }

        return ret;
    }

    int msg_fast::fast_process( xos_box::i_msg *& pMsg )
    {
        int ret = 0;

        connection * pConnect = (connection *)pMsg->get_void( 0, 0 );
        net::i_connect * pNetCon = pConnect->get_net_connect();

        if( ( 0 == ret ) && pConnect->m_pProcTask )
        {
            ret = 1;
        }

        if( 0 == ret )
        {
            if( pConnect->m_task_list.size() > 0 )
            {
                pConnect->m_pProcTask = pConnect->m_task_list.front();
            }
            if( pConnect->m_pProcTask )
            {
                pConnect->m_task_list.pop_front();
            }
            else
            {
                ret = 2;
            }
        }

        if( 0 == ret )
        {
            pConnect->m_pProcTask->get_task_info_from_http();
        }

        // 加入的后门，可以通过它直接命令程序退出
        if( 0 == ret )
        {
            task::T * pTask = pConnect->m_pProcTask;
            http_proc obj;
            int r = obj.helper_quit_test( pMsg );
            if( 0 == r )
            {
                pMsg->set_bool( 1, false );
                pMsg->set_bool( 2, true );
                pMsg->set_void( 0, pTask );
                pTask->get_connect()->fast_notify()->notify( pMsg, FAST_COMPOSE_RETURN );
                pNetCon = 0;
                ret = 3;
            }
        }

        // 真正处理请求的uri
        if( 0 == ret )
        {
            pMsg->set_void( 0, pConnect->m_pProcTask );
            pMsg->set_bool( 1, false );
            pMsg->set_bool( 2, false );
            http_proc obj;
            obj.proc( pMsg );
            pNetCon = 0;
        }

        xos_stl::release_ref( pNetCon );

        return ret;
    }

    int msg_fast::fast_compose_return( xos_box::i_msg *& pMsg )
    {
        int ret = 0;

        task::T * pTask = (task::T *)pMsg->get_void( 0, 0 );
        pTask->http_response()->compose( pMsg );

        return ret;
    }

    int msg_fast::fast_send( xos_box::i_msg *& pMsg )
    {
        int ret = 0;

        task::T * pTask = (task::T *)pMsg->get_void( 0, 0 );
        connection * pConnect = (connection *)pTask->m_pConnect;
        {
            xos_box::i_list * pList = pTask->http_response()->send_list();
            pConnect->encode( pList );
            bool bCloseAfterSend = pMsg->get_bool( 1, 0 );
            bool bQuitAfterSend = pMsg->get_bool( 2, 0 );
            notify_tcp obj;
            obj.post_send( pConnect, pList, bCloseAfterSend, bQuitAfterSend );
        }
        {
            xos_stl::term_pool_item( pTask );
            pConnect->m_pProcTask = 0;
        }
        // 处理下一个http请求（如果有的话）
        // 如果没有，就会释放计数保护
        // 停止这轮处理
        {
            pMsg->set_void( 0, pConnect );
            pConnect->fast_notify()->notify( pMsg, FAST_PROCESS );
        }

        return ret;
    }

} // xos_http
